package ruler.services;

import java.util.HashMap;
import java.util.List;
import ruler.main.R;
import ruler.rules.Rule;
import ruler.rules.Rule.DEVICE_TYPE;
import ruler.rules.Rule.RULE_TYPE;
import ruler.rules.storage.RulesHash;
import ruler.rules.storage.RulesStore;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.preference.PreferenceManager;
import android.util.Log;

public class PollingTask implements Runnable {

	private RulerService rulerService;
	private int maxAppsToPoll = Integer.MAX_VALUE;
	boolean pollAllApps = false;

	private List<Rule> enableWifiRulesList;
	private List<Rule> disableWifiRulesList;
	private List<Rule> enableGPSRulesList;
	private List<Rule> disableGPSRulesList;

	boolean shouldTurnOnWifi;
	boolean shouldTurnOffWifi;
	boolean shouldTurnOnGPS;
	boolean shouldTurnOffGPS;

	HashMap<String, RULE_TYPE> runningAppsAndServices;

	public PollingTask(RulerService rulerService) {
		super();
		this.rulerService = rulerService;
	}

	public void run() {
		long startTime = System.currentTimeMillis();
		Log.v("TASK", "POOLING");
		readPreferences();
		loadRules();
		polling();
		validateRules();
		toogleDevices();
		long endTime = System.currentTimeMillis();
		Log.v("TASK", "Total Time = " + (endTime - startTime) + " ms.");
	}

	private void loadRules() {
		long rulesStartTime = System.currentTimeMillis();
		RulesHash rules = RulesStore.Load();
		enableWifiRulesList = rules.getRules(DEVICE_TYPE.WIFI, true);
		disableWifiRulesList = rules.getRules(DEVICE_TYPE.WIFI, false);
		enableGPSRulesList = rules.getRules(DEVICE_TYPE.GPS, true);
		disableGPSRulesList = rules.getRules(DEVICE_TYPE.GPS, false);
		long rulesEndTime = System.currentTimeMillis();
		Log.v("TASK", "Load Rules Time = " + (rulesEndTime - rulesStartTime)
				+ " ms.");
	}

	private void polling() {
		long pollingStartTime = System.currentTimeMillis();
		runningAppsAndServices = getRunningAppsAndServices();
		long pollingEndTime = System.currentTimeMillis();
		Log.v("TASK", "Polling Time = " + (pollingEndTime - pollingStartTime)
				+ " ms.");
	}

	private void validateRules() {
		long validationStartTime = System.currentTimeMillis();
		shouldTurnOnWifi = validateRulesList(enableWifiRulesList,
				runningAppsAndServices);
		shouldTurnOffWifi = validateRulesList(disableWifiRulesList,
				runningAppsAndServices);
		shouldTurnOnGPS = validateRulesList(enableGPSRulesList,
				runningAppsAndServices);
		shouldTurnOffGPS = validateRulesList(disableGPSRulesList,
				runningAppsAndServices);
		long validationEndTime = System.currentTimeMillis();
		Log.v("TASK", "Validation Time = "
				+ (validationEndTime - validationStartTime) + " ms.");
	}

	private boolean validateRulesList(List<Rule> list,
			HashMap<String, RULE_TYPE> runningAppsAndServices) {
		int enableCount = 0;
		for (Rule rule : list) {
			if (rule.isEnable())
				enableCount++;
			if (!rule.isValid(runningAppsAndServices))
				return false;
		}
		return enableCount > 0;
	}

	private void toogleDevices() {
		long deviceToggleStartTime = System.currentTimeMillis();
		WifiManager wifiManager = (WifiManager) rulerService
				.getSystemService(Context.WIFI_SERVICE);
		LocationManager locationManager = (LocationManager) rulerService
				.getSystemService(Context.LOCATION_SERVICE);
		if (shouldTurnOffWifi && wifiManager.isWifiEnabled()) {
			wifiManager.setWifiEnabled(false);
			Log.v("TASK", "Your Wifi is Disabled");
		} else {
			if (shouldTurnOnWifi && !wifiManager.isWifiEnabled()) {
				wifiManager.setWifiEnabled(true);
				Log.v("TASK", "Your Wifi is Enable");
			}
		}
		if (shouldTurnOffGPS
				&& locationManager
						.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
			toggleGPS();
			Log.v("TASK", "Your GPS is Disabled");
		} else {
			if (shouldTurnOnGPS
					&& !locationManager
							.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
				toggleGPS();
				Log.v("TASK", "Your GPS is Enabled");
			}
		}
		long deviceToggleEndTime = System.currentTimeMillis();
		Log.v("TASK", "Device Toggle Time = "
				+ (deviceToggleEndTime - deviceToggleStartTime) + " ms.");
	}

	private HashMap<String, RULE_TYPE> getRunningAppsAndServices() {
		ActivityManager activityManager = (ActivityManager) this.rulerService
				.getSystemService(Context.ACTIVITY_SERVICE);
		List<RunningTaskInfo> runningTasks = activityManager
				.getRunningTasks(maxAppsToPoll);
		List<RunningServiceInfo> runningServices = activityManager
				.getRunningServices(maxAppsToPoll);
		HashMap<String, RULE_TYPE> runningAppsAndServices = new HashMap<String, Rule.RULE_TYPE>();
		PackageManager pm = rulerService.getPackageManager();
		for (RunningTaskInfo task : runningTasks) {
			try {
				CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(
						task.topActivity.getPackageName(),
						PackageManager.GET_META_DATA));
				runningAppsAndServices.put(c.toString(), RULE_TYPE.APP);
			} catch (Exception e) {
				runningAppsAndServices.put(task.topActivity.getPackageName(),
						RULE_TYPE.APP);
			}
		}
		for (RunningServiceInfo service : runningServices) {
			try {
				CharSequence c = pm.getApplicationLabel(pm.getApplicationInfo(
						service.process, PackageManager.GET_META_DATA));
				runningAppsAndServices.put(c.toString(), RULE_TYPE.SERVICE);
			} catch (Exception e) {
				runningAppsAndServices.put(service.service.getPackageName(),
						RULE_TYPE.SERVICE);
			}
		}
		return runningAppsAndServices;
	}

	private void readPreferences() {
		long preferenceStartTime = System.currentTimeMillis();
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(rulerService.getBaseContext());
		maxAppsToPoll = prefs
				.getInt(rulerService.getResources().getString(
						R.string.polledAppsCount), Integer.MAX_VALUE);
		pollAllApps = prefs.getBoolean(
				rulerService.getResources().getString(R.string.pollAllApps),
				false);
		if (pollAllApps)
			maxAppsToPoll = Integer.MAX_VALUE;
		long preferenceEndTime = System.currentTimeMillis();
		Log.v("TASK", "Preference Time = "
				+ (preferenceEndTime - preferenceStartTime) + " ms.");
	}

	private void toggleGPS() {
		Intent poke = new Intent();
		poke.setClassName("com.android.settings",
				"com.android.settings.widget.SettingsAppWidgetProvider");
		poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
		poke.setData(Uri.parse("3"));
		rulerService.sendBroadcast(poke);
	}

}